#include <stdlib.h>
#include <time.h>
#include "Game.h"
#include "Screen.h"
#include "GameState.h"
#include "EventPoller.h"
#include "Timer.h"
#include "Mouse.h"
#include "ClientState.h"
#include "Client.h"
#include "GMClientDisconnectRequest.h"
#include "GameMessageFactory.h"
#include "Server.h"

#ifdef WIN32
#include <crtdbg.h>
#endif
Game::Game()
{
	m_running = true;
	m_currentState = 0;
	m_requestState = 0;
}

int Game::Execute(int argc, char* argv[])
{
    /* Before starting the game, connect to the server */
    if(argc < 3 )
    {
        return 1;
    }
    const char* ipAdd = argv[1];
    int port = atoi(argv[2]);

    if(!TheClient::Instance()->ConnectToServer(std::string(ipAdd), port))
    {
        return 1;
    }
    /*   */

	if(!Initialise())
	{
		return -1;
	}

	while(m_running)
	{   
        //ScanForInput();
		ManageStates();
		TheEventPoller::Instance()->Update();
		Update();
		Draw();
		SDL_Delay(1);
	}

	CleanUp();
	return 0;
}

bool Game::Initialise()
{
	//Initialise the Screen.
	if(TheScreen::Instance()->Init(512,512,true) == false)
	{
		return false;
	}

    TheClientState::Instance()->Initialise();
	m_currentState = TheClientState::Instance();

    //Report Memory leaks on close
#ifdef WIN32
#if  defined (_DEBUG) | defined (DEBUG)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
#endif

	//Game is only initialsed once, makes sense to do it here.
    TheEventPoller::Instance()->AddHandler(this);

    // Seed the random-number generator with the current time 
    // so that the numbers will be different every time we run.
    srand( (unsigned)time( NULL ) );

    //SDL_EnableKeyRepeat(1,15);

	return true;
}

void Game::Update()
{
	TheTimer::Instance()->Update();
	TheMouse::Instance()->Update();
	m_currentState->Update();
}

void Game::Draw()
{
	m_currentState->Draw();
	TheScreen::Instance()->Flip();
}

void Game::CleanUp()
{
    if(m_currentState)
			m_currentState->CleanUp();

    TheClient::Instance()->ShutDown();
    TheScreen::Instance()->CleanUp();
    TheServer::Kill();
    TheClient::Kill();
    TheGameMessageFactory::Kill();
    TheClientState::Kill();
    TheScreen::Kill();
    TheEventPoller::Kill();
    TheTimer::Kill();
    TheMouse::Kill();
    TheGame::Kill();
	SDL_Quit();
}

void Game::Quit()
{
    GMClientDisconnectRequest gm;
    gm.SetID(TheClient::Instance()->GetID());
    TheClient::Instance()->SendToServer(gm);
    m_running = false;
}


void Game::ChangeState(SDL_GameState* gs)
{
    TheEventPoller::Instance()->RemoveHandler(m_currentState);
	m_currentState = gs;
}


void Game::RequestChange(SDL_GameState* gs)
{
	//only changes state at start of main loop
	m_requestState = gs;
}

void Game::ManageStates()
{
	//if there is a request state pending
	if(m_requestState != 0)
	{
		//and it is not initialised
		if ( !m_requestState->IsInitialised())
		{		
            //clean up the old state
			m_currentState->CleanUp();

			//initialise the new state,
			m_requestState->Initialise();

			//add it to the poller(may already be done, but using a set)
			TheEventPoller::Instance()->AddHandler(m_requestState);

			//change the state
			ChangeState(m_requestState);
			m_requestState = 0;
		}
		else
		{
			//as above, without the initialise.
			m_currentState->CleanUp();
			ChangeState(m_requestState);
			m_requestState->OnResume();
			TheEventPoller::Instance()->AddHandler(m_requestState);
			m_requestState = 0;
		}
		
	}
}

void Game::ScanForInput()
{
    static float count = 0;
    static int time = 10;

    count += TheTimer::Instance()->GetDtSeconds();

    if(count > time)
    {
        SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
        SDL_InitSubSystem(SDL_INIT_JOYSTICK);
        for(int i = 0; i < SDL_NumJoysticks(); ++i)
            SDL_JoystickOpen(i);
        count *= 0;
    }
}

